﻿Imports Kairyu.Save

''' <summary>
''' ログ生成管理クラス
''' </summary>
''' <remarks></remarks>
Public Class Log

    '#99 ロギングをNLogにする
    Private Shared logger As NLog.Logger = NLog.LogManager.GetCurrentClassLogger

    Private Shared Sub DefaultExecuteLog(sender As Object, e As CreateDbCommandEventArgs)
        Dim act As Action(Of String)
        Select Case e.CommandInfoLevel
            Case InfoLevelEnum.Info
                act = AddressOf logger.Info
            Case InfoLevelEnum.Warn
                act = AddressOf logger.Warn
            Case Else
                act = AddressOf logger.Debug
        End Select

        act.Invoke(e.ToString)
    End Sub

    Private Shared Sub DeaultFinishLog(sender As Object, e As FinishEventArgs)
        logger.Info(e.ToString)
    End Sub

    Private Shared Sub DeaultExceptionLog(sender As Object, e As DbCommandExceptionEventArgs)
        logger.ErrorException(e.ToString, e.Exception)
    End Sub

#Region "Mapping Event"
    Private Shared _onExecuteCommand As Action(Of Object, CreateDbCommandEventArgs) = AddressOf DefaultExecuteLog
    ''' <summary>
    ''' コマンド生成時通知先関数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Obsolete("OnExecuteCommandを使用してください")>
    Public Shared Property OnCreateCommand As Action(Of Object, CreateDbCommandEventArgs)
        Get
            Return OnExecuteCommand
        End Get
        Set(value As Action(Of Object, CreateDbCommandEventArgs))
            OnExecuteCommand = value
        End Set
    End Property

    ''' <summary>
    ''' コマンド実行時通知先関数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Property OnExecuteCommand As Action(Of Object, CreateDbCommandEventArgs)
        Get
            If _onExecuteCommand Is Nothing Then Return Sub() Return
            Return _onExecuteCommand
        End Get
        Set(value As Action(Of Object, CreateDbCommandEventArgs))
            _onExecuteCommand = value
        End Set
    End Property

    Private Shared _OnFinish As Action(Of Object, FinishEventArgs) = AddressOf DeaultFinishLog
    ''' <summary>
    ''' 終了時通知先関数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Property OnFinish As Action(Of Object, FinishEventArgs)
        Get
            If _OnFinish Is Nothing Then Return Sub() Return
            Return _OnFinish
        End Get
        Set(value As Action(Of Object, FinishEventArgs))
            _OnFinish = value
        End Set
    End Property

    Private Shared _OnException As Action(Of Object, DbCommandExceptionEventArgs) = AddressOf DeaultExceptionLog
    ''' <summary>
    ''' 例外時通知先関数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Property OnException As Action(Of Object, DbCommandExceptionEventArgs)
        Get
            If _OnException Is Nothing Then Return Sub() Return
            Return _OnException
        End Get
        Set(value As Action(Of Object, DbCommandExceptionEventArgs))
            _OnException = value
        End Set
    End Property

    Private Shared _OnOneModelManySave As Action(Of Object, ManySaveEventArgs)
    ''' <summary>
    ''' 1モデル複数更新時通知関数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks>
    ''' #67　トリガを使うとORMが失敗するときがある
    ''' モデル保存時、ORMでの更新件数とトリガの更新件数を合計して返されるため、
    ''' モデルの更新件数が1以外でも必ずしもエラーだといえない。
    ''' </remarks>
    Public Shared Property OnOneModelManySave As Action(Of Object, ManySaveEventArgs)
        Get
            '何も指定していない場合は、従来通りManySaveExceptionを発生させます。
            If _OnOneModelManySave Is Nothing Then Return Sub(obj, args) Throw New ManySaveException(obj, args)
            Return _OnOneModelManySave
        End Get
        Set(value As Action(Of Object, ManySaveEventArgs))
            _OnOneModelManySave = value
        End Set
    End Property
#End Region

#Region "DoCreateCommandAction"
    Friend Shared Function DoExecuteCommandAction(ByVal sender As Object, ByVal cmd As IDbCommand, level As InfoLevelEnum) As CreateDbCommandEventArgs
        Return DoExecuteCommandAction(sender, cmd, String.Empty, level)
    End Function

    Friend Shared Function DoExecuteCommandAction(ByVal sender As Object, ByVal cmd As IDbCommand, ByVal rootTableName As String, level As InfoLevelEnum) As CreateDbCommandEventArgs
        Dim e = New CreateDbCommandEventArgs(rootTableName, cmd) With {.CommandInfoLevel = level}
        OnExecuteCommand.Invoke(sender, e)
        Return e
    End Function
#End Region

#Region "DoFinishAction"
    Public Shared Sub DoFinishAction(ByVal sender As Object, ByVal totalmsec As Long, ByVal rows As Long, ByVal workTimes As Dictionary(Of String, Long))
        DoFinishAction(sender, New FinishEventArgs(totalmsec, rows, workTimes))
    End Sub

    Public Shared Sub DoFinishAction(ByVal sender As Object, ByVal e As FinishEventArgs)
        OnFinish.Invoke(sender, e)
    End Sub
#End Region

#Region "OnException"
    ''' <summary>
    ''' 例外処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="cmd"></param>
    ''' <remarks>#99 ロギングをNLogにする</remarks>
    Public Shared Sub DoExceptionAction(sender As Object, cmd As IDbCommand, ex As Exception)
        OnException.Invoke(sender, New DbCommandExceptionEventArgs(cmd, ex))
    End Sub
#End Region

End Class
